﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
using System.Threading;

namespace ComToKey
{
    public class RingBuf
    {  
        private int head = 0;
        private int tail = 0;
        const int buf_size = 1024 * 10;
        private byte[] selfbuf;
        private Semaphore ringbuf_sem = new Semaphore(1, 1);
 
        public RingBuf()
        {
            head = 0;
            tail = 0;
            selfbuf = new byte[buf_size];
            ringbuf_sem = new Semaphore(1, 1);
        }
        public RingBuf(int size)
        {
            head = 0;
            tail = 0;
            selfbuf = new byte[size];
            ringbuf_sem = new Semaphore(1, 1);
        }
        private bool AddAByteToBuf(byte abyte)
        {
            selfbuf[tail++] = abyte;
            tail %= selfbuf.Length;
            if (tail == head)
            {
                head++;
                head %= selfbuf.Length;
            }
            return true;
        }
        /// <summary>
        /// 向缓冲区中添加数据
        /// </summary>
        /// <param name="add_buf"></param>
        /// <returns></returns>
        public bool AddDataToBuf(byte[] add_buf)
        {
            int i = 0;

            ringbuf_sem.WaitOne();
            for (i = 0; i < add_buf.Length; i++ )
            {
                AddAByteToBuf(add_buf[i]);
            }
            ringbuf_sem.Release();
            return true;
        }
        public int GetDataLen()
        {
            int len = 0;

            ringbuf_sem.WaitOne();
            len = (selfbuf.Length + tail - head) % selfbuf.Length;
            ringbuf_sem.Release();
            return len;
        }
        private bool ReadAByteFromBuf(out byte abyte)
        {
            if (tail == head)
            {
                abyte = 0;
                return false;
            }
            abyte = selfbuf[head++];
            head %= selfbuf.Length;
            return true;
        }
        public int ReadDataFromBuf(byte[] f_buf, bool clear)
        {
            int len_tmp = 0;
            int i = 0;
            int head_tmp = 0;

            ringbuf_sem.WaitOne();
            len_tmp = (selfbuf.Length + tail - head) % selfbuf.Length;
            len_tmp = Math.Min(len_tmp, f_buf.Length);
            if (clear)
            {
                for (i = 0; i < len_tmp; i++)
                {
                    ReadAByteFromBuf(out f_buf[i]);
                }
            }
            else
            {
                /*如果不清除，暂保存下头指针，读完后在恢复*/
                head_tmp = head;
                for (i = 0; i < len_tmp; i++ )
                {
                    ReadAByteFromBuf(out f_buf[i]);
                }
                head = head_tmp;
            }
            ringbuf_sem.Release();
            return len_tmp;
        }
        public int DelDatalen(int len)
        {
            int len_tmp = 0;

            ringbuf_sem.WaitOne();
            len_tmp = (selfbuf.Length + tail - head) % selfbuf.Length;
            len = Math.Min(len, len_tmp);
            head += len;
            head %= selfbuf.Length;
            ringbuf_sem.Release();
            return len;
        }
        public bool ClearData()
        {
            int len_tmp = 0;

            ringbuf_sem.WaitOne();
            len_tmp = (selfbuf.Length + tail - head) % selfbuf.Length;
            head += len_tmp;
            head %= selfbuf.Length;
            ringbuf_sem.Release();
            return true;
        }
    }
}
